package com.nuanshui.heatedloan.controller.display.users;

import com.alibaba.dubbo.config.annotation.Reference;
import com.nuanshui.framework.cache.CacheConstants;
import com.nuanshui.framework.exception.BizException;
import com.nuanshui.framework.exception.GlobalErrorCode;
import com.nuanshui.framework.lang.DateUtil;
import com.nuanshui.framework.lang.SysStringUtils;
import com.nuanshui.framework.security.DESC;
import com.nuanshui.framework.springContext.SpringPropertiesUtil;
import com.nuanshui.framework.utils.LogUtil;
import com.nuanshui.framework.utils.SSOTokenUtil;
import com.nuanshui.framework.utils.TokenProcessor;
import com.nuanshui.framework.utils.redis.JedisUtil;
import com.nuanshui.heatedloan.baseservice.model.UserAgent;
import com.nuanshui.heatedloan.constant.GlobalParam;
import com.nuanshui.heatedloan.controller.BaseController;
import com.nuanshui.heatedloan.controller.ResponseObject;
import com.nuanshui.heatedloan.credit.facade.CustomerCreditResultService;
import com.nuanshui.heatedloan.credit.vo.CustomerCreditResultVO;
import com.nuanshui.heatedloan.extension.security.SecurityContextService;
import com.nuanshui.heatedloan.msgcenter.facade.VerificationFacade;
import com.nuanshui.heatedloan.msgcenter.model.AliSmsSecurityCodeTemplateEnum;
import com.nuanshui.heatedloan.service.services.SafeTokenUtil;
import com.nuanshui.heatedloan.userinfo.constant.IntegralActionType;
import com.nuanshui.heatedloan.userinfo.constant.LoginAccountType;
import com.nuanshui.heatedloan.userinfo.facade.*;
import com.nuanshui.heatedloan.userinfo.facade.thirdlogin.ThirdUserService;
import com.nuanshui.heatedloan.userinfo.facade.thirdlogin.ThirdUserServiceFactory;
import com.nuanshui.heatedloan.userinfo.facade.wechat.WeChatService;
import com.nuanshui.heatedloan.userinfo.form.BoundUserForm;
import com.nuanshui.heatedloan.userinfo.form.SendMsgForm;
import com.nuanshui.heatedloan.userinfo.form.UserForm;
import com.nuanshui.heatedloan.userinfo.model.*;
import com.nuanshui.heatedloan.userinfo.tool.UserTool;
import com.nuanshui.heatedloan.userinfo.vo.AccountBindStatusVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.support.RequestContext;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author jamesp
 */
@RestController
public class UserAuthController extends BaseController {

	private static final String SMS_VERIFIED = "sms_verified";
	// 1表示成功
	private static final String BIND_PHONE_SMS_SUCCESS = "1";
	// 2表示手机号已经存在
	private static final String BIND_PHONE_SMS_EXIST = "2";
	// 表示手机账号不能绑定
	private static final String BIND_PHONE_ERROR = "0";

	@Reference(url=GlobalParam.USER_DUBBO_SERVER,timeout=GlobalParam.DUBBO_SERVER_TIME_OUT,version = GlobalParam.USER_DUBBO_SERVER_VERSION)
	private UserService userService;

	@Reference(url=GlobalParam.USER_DUBBO_SERVER,timeout=GlobalParam.DUBBO_SERVER_TIME_OUT,version = GlobalParam.USER_DUBBO_SERVER_VERSION)
	private UserQueryService userQueryService;

	@Reference(url=GlobalParam.USER_DUBBO_SERVER,timeout=GlobalParam.DUBBO_SERVER_TIME_OUT,version = GlobalParam.USER_DUBBO_SERVER_VERSION)
	private UserStateService userStateService;

	@Reference(url=GlobalParam.USER_DUBBO_SERVER,timeout=GlobalParam.DUBBO_SERVER_TIME_OUT,version = GlobalParam.USER_DUBBO_SERVER_VERSION)
	private UserTokenService userTokenService;

	@Reference(url=GlobalParam.USER_DUBBO_SERVER,timeout=GlobalParam.DUBBO_SERVER_TIME_OUT,version = GlobalParam.USER_DUBBO_SERVER_VERSION)
	private UserWeixinAccountService userWeixinAccountService;
	
	@Reference(url=GlobalParam.USER_DUBBO_SERVER,timeout=GlobalParam.DUBBO_SERVER_TIME_OUT,version = GlobalParam.USER_DUBBO_SERVER_VERSION)
	private UserLogicService userLogicService;
	
	@Reference(url=GlobalParam.USER_DUBBO_SERVER,timeout=GlobalParam.DUBBO_SERVER_TIME_OUT,version = GlobalParam.USER_DUBBO_SERVER_VERSION)
	private UserTool userTool;
	
	@Reference(url=GlobalParam.USER_DUBBO_SERVER,timeout=GlobalParam.DUBBO_SERVER_TIME_OUT,version = GlobalParam.USER_DUBBO_SERVER_VERSION)
	private WeChatService weChatService;

	@Autowired
	private JedisUtil jedisUtil;	
	@Autowired
	private ThreadPoolTaskExecutor taskExecutor;
	@Reference(url = GlobalParam.MSGCENTER_DUBBO_SERVER, timeout = GlobalParam.DUBBO_SERVER_TIME_OUT,version = GlobalParam.MSGCENTER_DUBBO_SERVER_VERSION )
	private VerificationFacade veriFacade;

	@Reference(url = GlobalParam.CREDIT_DUBBO_SERVER, timeout = GlobalParam.DUBBO_SERVER_TIME_OUT,version = GlobalParam.CREDIT_DUBBO_SERVER_VERSION )
	private CustomerCreditResultService customerCreditResultService;
	
	@Autowired
	private SSOTokenUtil ssoTokenUtil;

	@Autowired
	private PasswordEncoder pwdEncoder;

	@Autowired
	private SecurityContextService securityContextService;

	private Logger logger = LoggerFactory.getLogger("user_login");

	@Autowired
	private SafeTokenUtil safeTokenUtil;

	/**
	 * 检查用户手机号是否注册
	 * 
	 * @param form
	 * @param errors
	 * @return
	 */
	@RequestMapping("/registered")
	public String isRegistered(@Valid UserForm form, Errors errors) {
		return success(userService.isRegistered(form.getMobile()));
	}

	/**
	 * 注册 step1:校验验证码
	 * 
	 * @param form
	 *            : mobile + smscode
	 */
	@RequestMapping("/register/verify")
	public ResponseObject<Boolean> registerVerify(@Valid @ModelAttribute UserForm form, Errors errors,
			HttpServletRequest req, HttpServletResponse resp) {

		req.getSession().setAttribute(SMS_VERIFIED, Boolean.FALSE);

		Boolean valid = veriFacade.verifyCode(form.getMobile(), form.getSmsCode(), AliSmsSecurityCodeTemplateEnum.ALI_SIGN);
		if (!valid) {
			log.error("regist verify error, invalid smscode, mobile:" + form.getMobile() + " smsCode:"+ form.getSmsCode());
			throw new BizException(GlobalErrorCode.UNKNOWN, "验证码不正确");
		}

		req.getSession().setAttribute(SMS_VERIFIED, Boolean.TRUE);
		return new ResponseObject<Boolean>(true);
	}

	@RequestMapping("verifyNickname")
	public ResponseObject<Boolean> verifyNickname(String nickname) {
		return new ResponseObject<Boolean>(userStateService.userCountByNick(nickname) <= 0);
	}

	/**
	 * 注册 step2:接收密码创建用户
	 * 
	 * @param form
	 *            : mobile + pwd
	 */
	@RequestMapping("/register/create")
	public String registerCreate(@Valid @ModelAttribute UserForm form, Errors errors, HttpServletRequest req,
			HttpServletResponse resp) {

		LogUtil.info(logger, "----------<手机号注册用户>----------");
		if (!veriFacade.verifyCode(form.getMobile(), form.getSmsCode(), AliSmsSecurityCodeTemplateEnum.ALI_SIGN)) {
			RequestContext requestContext = new RequestContext(req);
			LogUtil.info(logger, "----------<手机号注册用户> 错误: 验证码不正确----------");
			throw new BizException(GlobalErrorCode.UNKNOWN, "验证码不正确");
		}

		if (form.getPwd() == null || form.getPwd().length() < 6 || form.getPwd().length() > 50) {
			RequestContext requestContext = new RequestContext(req);
			LogUtil.info(logger, "----------<手机号注册用户> 错误: 验证码不正确----------");
			throw new BizException(GlobalErrorCode.INVALID_ARGUMENT,
					requestContext.getMessage("register.password.invalid"));
		}
		User newUser = userService.register(form.getMobile(), form.getPwd());
		UserAgent userAgent = (UserAgent) req.getAttribute(GlobalParam.USER_AGENT);
		String safeToken = userAgent.getSafeToken();

		LogUtil.info(logger,  String.format("----------<手机号注册用户> 自动登录, 用户id: %s 绑定的safeToken是: %s----------", newUser.getId(), safeToken));
		// 自动登录
		securityContextService.setAuthentication(newUser);
		userTool.incrUserIntegral(newUser.getId(),IntegralActionType.BIND_PHONE);

		return success(loadCurrentUserInfo());
	}

	/**
	 * 忘记密码验证
	 * 
	 * @param
	 * @author guohao
	 * @date 2015年5月6日 上午9:39:28
	 */
	@Deprecated
	@RequestMapping("/validate-dynamic-pwd")
	public String loginDynamicPwdValidate(@Valid UserForm form, Errors errors, HttpServletRequest req,
			HttpServletResponse resp) {
		if (!veriFacade.verifyCode(form.getMobile(), form.getSmsCode(), AliSmsSecurityCodeTemplateEnum.ALI_DYNAMIC_PWD)) {
			new RequestContext(req);
			throw new BizException(GlobalErrorCode.UNKNOWN, "验证码错误");
		}

		User newUser = userQueryService.loadByLoginName(form.getMobile());
		if (newUser == null)
			throw new BizException(GlobalErrorCode.UNKNOWN, "该手机号未注册");
		Integer versionInt = 0;
		if (!StringUtils.isEmpty(form.getVersion())) {
			versionInt = Integer.parseInt(form.getVersion().replace(".", ""));
		}

		if (versionInt >= 120 && StringUtils.isEmpty(form.getPwd())) {
			throw new BizException(GlobalErrorCode.UNKNOWN, "密码不能为空");
		}
		if (!StringUtils.isEmpty(form.getPwd())) {
			newUser.setPassword(pwdEncoder.encode(form.getPwd()));
			userService.updateUserInfo(newUser, false);
		}
		securityContextService.setAuthentication(newUser);


		return success(loadCurrentUserInfo());
	}


	/**
	 * 动态密码登录，如果没有这个用户则执行创建
	 * 
	 * @author Gonzo
	 * @date 2016年7月12日下午3:43:00
	 * @return
	 */
	@RequestMapping("/validate-dynamic-login")
	public String dynamicLogin(@Valid UserForm form, Errors errors, HttpServletRequest req, HttpServletResponse resp) {

		LogUtil.info(logger, "----------<动态密码登录>----------");
		// 首先，先校验验证码
		if (!veriFacade.verifyCode(form.getMobile(), form.getSmsCode(), AliSmsSecurityCodeTemplateEnum.ALI_DYNAMIC_DYNAMICORREGI)) {
			LogUtil.info(logger, "----------<动态密码登录> 错误: 验证码错误 ----------");
			throw new BizException(GlobalErrorCode.UNKNOWN, "验证码错误");
		}

		// 然后判断当前手机号码是否注册过用户
		User newUser = userQueryService.loadByLoginName(form.getMobile());
		if (newUser == null) {
			// 如果没有注册过，则注册 这里密码为空?
			newUser = userService.register(form.getMobile(), null);
			LogUtil.info(logger, "----------<动态密码登录> 用户不存在, 创建用户----------");
		}

		// 自动登录
		securityContextService.setAuthentication(newUser);

		userTool.incrUserIntegral(newUser.getId(),IntegralActionType.BIND_PHONE);

		//更新userToken
		UserAgent userAgent =  (UserAgent) req.getAttribute(GlobalParam.USER_AGENT);
		userAgent.setUserId(newUser.getId());
		String deviceToken =userAgent.getDeviceToken();// 用户传进来的token
		String deviceType = userAgent.getClient();
		String version = userAgent.getVersion();
		userTokenService.addUserTokenOnAsyn(deviceToken, deviceType, version, newUser.getId());


		LogUtil.info(logger, String.format("----------<动态密码登录> 用户id: %s 绑定的safeToken是: %s----------", newUser.getId(), userAgent.getSafeToken()));
		return success(loadCurrentUserInfo());
	}

	/**
	 * 忘记密码验证smsCode，并改密
	 * 
	 * @param form
	 * @param errors
	 * @param req
	 * @param resp
	 * @return
	 */
	@RequestMapping("/validate-forget-pwd")
	public String validateForPwdChange(@Valid @ModelAttribute UserForm form, Errors errors, HttpServletRequest req,
			HttpServletResponse resp) {

		// valdiate code
		Boolean valid = veriFacade.verifyCode(form.getMobile(), form.getSmsCode(), AliSmsSecurityCodeTemplateEnum.ALI_DYNAMIC_PWD);
		if (!valid) {
			throw new BizException(GlobalErrorCode.UNKNOWN, "验证码不正确");
		}

		// set password empty
		//userService.emptyUserPassword(form.getMobile(), form.getSmsCode());

		User newUser = userQueryService.loadByLoginName(form.getMobile());

		boolean bFlag=userService.changePwd(null, form.getPwd(),newUser.getId());

		if(bFlag)
		   securityContextService.setAuthentication(newUser,true);


		return success(loadCurrentUserInfo());
	}

	@Deprecated
	@RequestMapping("userauth/updatePwd")
	public String updatePwd(@Valid @ModelAttribute UserForm form, Errors errors, HttpServletRequest req,
			HttpServletResponse resp) {

		// 首先，先校验验证码
		if (!veriFacade.verifyCode(form.getMobile(), form.getSmsCode(), AliSmsSecurityCodeTemplateEnum.ALI_UPDATE_PWD)) {
			new RequestContext(req);
			LogUtil.info(logger, "----------<动态密码登录> 错误: 验证码错误 ----------");
			throw new BizException(GlobalErrorCode.UNKNOWN, "验证码错误");
		}
		User newUser = userQueryService.loadByLoginName(form.getMobile());
		securityContextService.setAuthentication(newUser,true);

		userService.changePwd(form.getOldPwd(), form.getPwd(),getCurrentUser().getId());
		return success(loadCurrentUserInfo());

	}

	/**
	 * 未登录用户会跳到本页面；请使用 /signin_check?u=xx&p=yy 登录
	 * 
	 * @return 带http status code, 因为访问任何未授权页面，都会跳到这里。
	 */
	@RequestMapping(value = "/signin")
	@ResponseStatus(HttpStatus.UNAUTHORIZED)
	public ResponseObject<?> signinPage(HttpServletRequest req) {
		return new ResponseObject<Object>(new RequestContext(req).getMessage("signin.failed"),
				GlobalErrorCode.UNAUTHORIZED);
	}

	@RequestMapping("/logoutsuccess")
	public ResponseObject<Boolean> logoutSuccess() {

		return new ResponseObject<Boolean>(true);

	}

	/**
	 * 登录失败的用户跳到本解决
	 * 
	 * @param
	 * @author guohao
	 * @date 2015年5月6日 上午9:40:54
	 */
	@RequestMapping(value = "/signin_fail",method = RequestMethod.GET)
	public ResponseObject<?> signinFailedPage(HttpServletRequest req) {
		return new ResponseObject<Object>(new RequestContext(req).getMessage("signin.failed"),
				GlobalErrorCode.UNAUTHORIZED);
	}

	/**
	 * 判断用户是否已登录接口
	 * 
	 * @param
	 * @author guohao
	 * @date 2015年5月6日 上午9:41:36
	 */
	@RequestMapping(value=UserAuthApiConstant.signined)
	public String signined(HttpServletRequest request, String deviceToken, String version, String deviceType) {
		try {
			userTokenService.updateDeviceToken(deviceToken, deviceType, version,getCurrentUser().getId() );
			final UserAgent userAgent = (UserAgent) request.getAttribute(GlobalParam.USER_AGENT);
			if (!StringUtils.isEmpty(userAgent.getSafeToken())) {
				final String id = getCurrentUser().getId();
				taskExecutor.execute(new Runnable() {
					@Override
					public void run() {
						String safeToken = userAgent.getSafeToken();
						userTokenService.delUserSafeToken(safeToken, id);
						userTokenService.saveUserSafeToken(safeToken, id);
					}
				});
			}

			UserInfo userInfo = loadCurrentUserInfo();
			if (userInfo == null) {
				throw new BizException(GlobalErrorCode.UNAUTHORIZED, "用户未登陆");
			}
			userTool.incrUserIntegral(userInfo.getId(), IntegralActionType.SIGNIN);
			//判断这个人在不在组织内
			String userId = userInfo.getId();
			if (userId != null) {

			}

			if(userInfo.getIsInOrganization()==null)
			   userInfo.setIsInOrganization(0);
			//判断用户的权限
			return success(userInfo);
		} catch (BizException e) {
			e.printStackTrace();
			// 未登录状态
			throw new BizException(GlobalErrorCode.UNAUTHORIZED, "用户未登陆");
			// return new ResponseObject<UserInfo>();
		}
	}

	/**
	 * 修改密码
	 * 
	 * @param
	 * @author guohao
	 * @date 2015年5月6日 上午9:42:02
	 */
	@RequestMapping(value = "/user/change-pwd",method = RequestMethod.POST)
	public ResponseObject<Boolean> changePwd(@RequestParam(value = "oldPwd", required = false) String oldPwd,
			@RequestParam("newPwd") String newPwd, HttpServletRequest req) {
		if (org.apache.commons.lang3.StringUtils.isBlank(newPwd)) {
			RequestContext requestContext = new RequestContext(req);
			throw new BizException(GlobalErrorCode.INVALID_ARGUMENT,requestContext.getMessage("register.password.invalid"));
		}
		return new ResponseObject<Boolean>(userService.changePwd(oldPwd, newPwd,getCurrentUser().getId()));
	}


	@Reference(url=GlobalParam.USER_DUBBO_SERVER,timeout=GlobalParam.DUBBO_SERVER_TIME_OUT)
	private ThirdAuthService thirdAuthService;

	@Autowired
	private ThirdUserServiceFactory thirdUserServiceFactory;

	/**
	 * 第三方 登录
	 * 
	 * @param
	 * @author guohao
	 * @date 2015年5月6日 上午9:44:48
	 */
	@RequestMapping(value = "thirdCheckUser",method = RequestMethod.POST)
	@ResponseBody
	public String thirdCheckUser(BoundUserForm boundUserForm, HttpServletRequest req, HttpServletResponse resp)
			throws Exception {
		if (SysStringUtils.isEmpty(boundUserForm.getOpenid()))
			error("帐号不存在");


		LogUtil.info(logger, "----------<第三方登录>----------");

		boundUserForm.setChannel(getUserAgent().getChannel());

		User user = null;

		user=thirdAuthService.thirdCheckUser(boundUserForm);
		boolean isNew = user.getIsNew();

		securityContextService.setAuthentication(user);

		UserInfo u = userLogicService.loadCurrentUserInfo(user.getId(), true);
		if (u == null) {
			error("未注册");
			securityContextService.clearAuth();
		}
		userTokenService.updateDeviceToken(boundUserForm.getDeviceToken(), boundUserForm.getDeviceType(),
				boundUserForm.getVersion(), user.getId());

		u.setIsNew(isNew);
		if (isNew) {
			userTool.incrUserIntegral(user.getId(),IntegralActionType.BIND_ACCOUNT);
			if (!"藏友".equals(user.getNick())) {
				userTool.incrUserIntegral(user.getId(),IntegralActionType.PERSONAL_DATA);
			}
			if (!"寻宝之旅".equals(user.getSignature())) {
				userTool.incrUserIntegral(user.getId(),IntegralActionType.PERSONAL_DATA);
			}
		}
		u.setLoginAccountType(boundUserForm.getAccountType());

		UserAgent userAgent =  (UserAgent) req.getAttribute(GlobalParam.USER_AGENT);

		LogUtil.info(logger, String.format("----------<第三方登录>----------, 用户 id:%s 绑定的 safeToken 是:%s", u.getId(), userAgent.getDeviceToken()));
		return success(u);
	}

	/**
	 * 发送 绑定手机号验证码
	 * 
	 * @param form
	 *            with mobile
	 * @return 是否已发送sms
	 */
	@RequestMapping(value = "/sendBindUserCode",method = RequestMethod.POST)
	@ResponseBody
	public String sendBindUserSmsCode(@Valid @ModelAttribute SendMsgForm form, HttpServletResponse response,Errors errors, HttpServletRequest request, Integer length) {
		HashMap<String, Object> map = new HashMap<String, Object>();
		String openId = getWechatOpenId();
		getSafeToken();
		UserWeixinOpenId weixinOpenId = null;
		if (SysStringUtils.isNotEmpty(openId)) {
			weixinOpenId = userWeixinAccountService.loadByOpenId(openId);
		}
		// 表示第一次验证
		User u = userQueryService.loadUserByPhone(form.getMobile());
		if (u != null && !u.getId().equals(getCurrentUser().getId())) {
			if (isFromWechat()) {
				// 如果是微信的账号
				ThirdUser thirdUser =thirdUserServiceFactory.GetThirdUserService(LoginAccountType.WEI_XIN).loadThirdUser(u.getId());
				if (thirdUser != null && !weixinOpenId.getUnionId().equals(thirdUser.getUnionId())) {
					// 表示已经有微信账号已经绑定到此账号上了
					map.put("token", "");
					map.put("status", BIND_PHONE_ERROR);
					map.put("nickname", u.getNick());
				} else {
					map.put("status", BIND_PHONE_SMS_EXIST);
					map.put("nickname", u.getNick());
					veriFacade.generateCode(form.getMobile(), AliSmsSecurityCodeTemplateEnum.ALI_BOUND_USER, length);
				}
			} else {
				// 表示已经有微信账号已经绑定到此账号上了
				map.put("token", "");
				map.put("status", BIND_PHONE_ERROR);
				map.put("nickname", u.getNick());
			}

		} else {
			veriFacade.generateCode(form.getMobile(), AliSmsSecurityCodeTemplateEnum.ALI_BOUND_USER, length);
			map.put("status", BIND_PHONE_SMS_SUCCESS);
		}
		return success(map);

	}

	/**
	 * 判断手机是否绑定某种账号
	 * 
	 * @param
	 * @author guohao
	 * @date 2015年6月24日 上午10:46:24
	 */
	@SuppressWarnings("unused")
	private boolean isBinded(Integer accountType, String userId) {
		if (accountType == null)
			return false;

		return (loadAccountUser(accountType,userId) != null);
	}

	/**
	 * 验证 手机号是否存在
	 * 
	 * @param
	 * @author guohao
	 * @date 2015年5月25日 下午12:05:14
	 */
	@RequestMapping(value = "/verifyPhoneExist",method = RequestMethod.POST)
	@ResponseBody
	public ResponseObject<Boolean> verifyPhoneExist(String phone) {
		User u = userQueryService.loadByLoginName(phone);
		if (u != null && !u.getId().equals(getCurrentUser().getId())) {
			return new ResponseObject<Boolean>(true);

		}
		return new ResponseObject<Boolean>(false);

	}

	/**
	 * 校验绑定账号的验证码
	 * 
	 * @param form
	 *            : mobile + smscode
	 */
	@RequestMapping(value = "/bindUser/verify",method = RequestMethod.POST)
	@ResponseBody
	public ResponseObject<Boolean> bindUserVerify(@Valid @ModelAttribute UserForm form, Errors errors,
			HttpServletRequest req, HttpServletResponse resp) {

		req.getSession().setAttribute(SMS_VERIFIED, Boolean.FALSE);
		Boolean valid = veriFacade.verifyCode(form.getMobile(), form.getSmsCode(), AliSmsSecurityCodeTemplateEnum.ALI_BOUND_USER);
		if (!valid) {
			RequestContext requestContext = new RequestContext(req);
			log.error("regist verify error, invalid smscode, mobile:" + form.getMobile() + " smsCode:"
					+ form.getSmsCode());
			throw new BizException(GlobalErrorCode.UNKNOWN, requestContext.getMessage("register.smscode.not.valid"));
		}
		req.getSession().setAttribute(SMS_VERIFIED, Boolean.TRUE);
		return new ResponseObject<Boolean>(true);
	}

	private void bindCheck(BoundUserForm boundUserForm)
	{
		HttpServletRequest req=this.getRequest();
		if (boundUserForm.getAccountType() == LoginAccountType.PHONE) {
			// 如果是绑定 手机进行 短信校验
			req.getSession().setAttribute(SMS_VERIFIED, Boolean.FALSE);

			if (!veriFacade.verifyCode(boundUserForm.getPhone(), boundUserForm.getSmsCode(),
					AliSmsSecurityCodeTemplateEnum.ALI_BOUND_USER)) {
				throw new BizException(GlobalErrorCode.UNKNOWN, "验证码不正确~");
			}
		}
	}

	/**
	 * 绑定 用户账号
	 * 
	 * @param
	 * @author guohao
	 * @date 2015年5月6日 下午3:23:36
	 */
	@ResponseBody
	@RequestMapping(value = "bindUser",method = RequestMethod.POST)
	public String bindUser(BoundUserForm boundUserForm, HttpServletRequest req) {

		bindCheck(boundUserForm);

		userService.bindUser(boundUserForm);
		if (boundUserForm.getAccountType() == LoginAccountType.PHONE) {
			return success(true, userTool.incrUserIntegral(getCurrentUser().getId(),IntegralActionType.BIND_PHONE));
		} else {
			return success(true, userTool.incrUserIntegral(getCurrentUser().getId(),IntegralActionType.BIND_ACCOUNT));
		}
	}

	/**
	 * 微信段 绑定 用户账号
	 * 
	 * @param
	 * @author guohao
	 * @date 2015年5月6日 下午3:23:36
	 */
	@ResponseBody
	@RequestMapping(value = "/weixinBindUser",method = RequestMethod.POST)
	public String weixinBindUser(BoundUserForm boundUserForm) {

		bindCheck(boundUserForm);

		User user = userService.bindUser(boundUserForm);
		WechatUserInfo info = new WechatUserInfo();
		info.setOpenId(getWechatOpenId());
		info.setUserId(user.getId());
		info.setSafeToken(ssoTokenUtil.generateToken(user.getId(), getResponse()));
		if (boundUserForm.getAccountType() == LoginAccountType.PHONE) {
			return successWithoutNull(info, userTool.incrUserIntegral(user.getId(),IntegralActionType.BIND_PHONE));
		} else {
			return successWithoutNull(info, userTool.incrUserIntegral(user.getId(),IntegralActionType.BIND_ACCOUNT));
		}
	}

	/**
	 * 第一次生成新账号的时候进行收集绑定接口
	 * 
	 * @param
	 * @author guohao
	 * @date 2015年6月24日 上午10:41:09
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@RequestMapping(value = "/registerBindUser",method = RequestMethod.POST)
	public ResponseObject registerBindUser(BoundUserForm boundUserForm, HttpServletRequest req) {
		// 如果是绑定 手机进行 短信校验
		req.getSession().setAttribute(SMS_VERIFIED, Boolean.FALSE);
		Boolean valid = veriFacade.verifyCode(boundUserForm.getPhone(), boundUserForm.getSmsCode(), AliSmsSecurityCodeTemplateEnum.ALI_BOUND_USER);
		if (!valid) {
			RequestContext requestContext = new RequestContext(req);
			throw new BizException(GlobalErrorCode.UNKNOWN, requestContext.getMessage("register.smscode.not.valid"));
		}
		User user = userService.registerBindUser(boundUserForm);

		securityContextService.setAuthentication(user);

		userTokenService.updateDeviceToken(boundUserForm.getDeviceToken(), boundUserForm.getDeviceType(),
				boundUserForm.getVersion(), user.getId());
		req.getSession().getId();
		userTool.incrUserIntegral(user.getId(),IntegralActionType.BIND_PHONE);
		return new ResponseObject(loadCurrentUserInfo());
	}

	private ThirdUser loadAccountUser(int accountType,String userId)
	{
		ThirdUserService service=thirdUserServiceFactory.GetThirdUserService(accountType);
		if(service!=null)
		{
			return service.loadThirdUser(userId);
		}
		return null;
	}

	private AccountBindStatusVo addAccountBindStatus(int accountType,String userId,AccountBindStatus status)
	{
		ThirdUser user=loadAccountUser(accountType,userId);
		AccountBindStatusVo item=new AccountBindStatusVo(accountType, user!=null ? true : false);
		status.list.add(item);
		if (item.isBinded()) {
			status.bindCount++;
		}
		return item;
	}


	class AccountBindStatus
	{
		public Integer bindCount = 0;
		public List<AccountBindStatusVo> list = new ArrayList<AccountBindStatusVo>();
	}

	/**
	 * 账号绑定状态
	 * 
	 * @param
	 * @author guohao
	 * @date 2015年5月25日 上午10:07:57
	 */
	@RequestMapping(value = "/accountBindStatus",method = RequestMethod.POST)
	@ResponseBody
	public ResponseObject<HashMap<String, Object>> getAccountBindStatus() {
		String userId = getCurrentUser().getId();

		AccountBindStatus status=new AccountBindStatus();

		addAccountBindStatus(LoginAccountType.QQ,userId,status);
		addAccountBindStatus(LoginAccountType.WEI_XIN,userId,status);
		addAccountBindStatus(LoginAccountType.WEI_BO,userId,status);

		User user = userQueryService.load(userId);
		if (user == null) {
			throw new BizException(GlobalErrorCode.UNAUTHORIZED, "用户不存在，重新登陆");
		}
		if (StringUtils.isEmpty(user.getPhone())) {
			AccountBindStatusVo vo = new AccountBindStatusVo(LoginAccountType.PHONE, false);
			if (StringUtils.isEmpty(user.getPassword())) {
				String password = TokenProcessor.getInstance().generateToken(user.getId(), true);
				vo.setPassword(password);
				User u = getCurrentUser();
				u.setPassword(password);
			}
			status.list.add(vo);
		} else {
			AccountBindStatusVo vo = new AccountBindStatusVo(LoginAccountType.PHONE, true);
			vo.setPhone(user.getPhone());
			// 如果当前用户没有密码，那么就随机生成一个密码，并且保存到缓存中
			if (StringUtils.isEmpty(user.getPassword())) {
				String password = TokenProcessor.getInstance().generateToken(user.getPhone(), true);
				vo.setPassword(password);
				this.jedisUtil.set(com.nuanshui.framework.cache.CacheConstants.RANDOM_PWD_KEY + userId, password);
			}

			status.list.add(vo);
			status.bindCount++;
		}
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("bindCount", status.bindCount);
		map.put("accoutBoundStatus", status.list);
		return new ResponseObject<HashMap<String, Object>>(map);
	}

	/*
	 * bindCount [{}]
	 * 
	 */
	/**
	 * 解除用户的账号绑定
	 * 
	 * @param
	 * @author guohao
	 * @date 2015年5月7日 下午1:54:11
	 */
	@ResponseBody
	@RequestMapping(value = "/unBindUser",method = RequestMethod.POST)
	public ResponseObject<Boolean> unBindUser(Integer accountType) {
        String userId = getCurrentUser().getId();

	    userService.unBindUser(userId, accountType);
		userTool.incrUserIntegral(userId,IntegralActionType.UN_BIND_ACCOUNT);
		return new ResponseObject<Boolean>(true);
	}

	/**
	 * 获取当前登录 的用户
	 * 
	 * @param
	 * @author guohao
	 * @date 2015年5月6日 上午9:37:41
	 */
	private UserInfo loadCurrentUserInfo() {
		UserInfo userInfo = userLogicService.loadCurrentUserInfo(getCurrentUser().getId(), true);
		String phone=userInfo.getPhone();
		if (userInfo == null)
			return null;
		if(phone!=null){
			userInfo.setPhone(DESC.encrypt3DES(phone));
		}
		CustomerCreditResultVO customerCreditResultVO=customerCreditResultService.
				loadVOByUserId(getCurrentUser().getId());
		if(customerCreditResultVO==null||(customerCreditResultVO!=null&&customerCreditResultVO.getStatus()!=2)){
			userInfo.setVerified(false);
		}else {
			userInfo.setVerified(true);
		}
		String time = jedisUtil.get(CacheConstants.DENY_PUSH_POST_TIME + userInfo.getId());
		String key = CacheConstants.DENY_PUSH_POST + DateUtil.getToday("yyyy-MM-dd") + userInfo.getId();
		if (time != null) {
			Integer num = 0;
			if (jedisUtil.exists(key)) {
				// 如果key存在
				num = Integer.parseInt(jedisUtil.get(key));
			} else {
				num = Integer.parseInt(time);
			}
			userInfo.setLimitPostCount(num);
		}

		try {
			if (StringUtils.isEmpty(userInfo.getChatToken())) {
				userTool.updateChatToken(userInfo);
			}

		} catch (Exception e) {
			log.error("获取私信token失败", e);
		}
		return userInfo;
	}


	@RequestMapping(value = "/getUserSafeToken",method = RequestMethod.POST)
	public String getUserSafeToken(String type) {
		if ("1".equals(type)) {
			UserAgent userAgent = getUserAgent();
			String safeToken = safeTokenUtil.generateToken(userAgent.getVersion()).getValue();
			securityContextService.getCurrentUser();
			User user = this.userQueryService.getUserInfo(userAgent.getUserId());
			this.securityContextService.setAuthentication(user);
			this.securityContextService.createUserSession(safeToken);
			return success(safeToken);
		}
		return success();
	}

	@RequestMapping(value = "generateToken",method=RequestMethod.POST)
	public String generateToken(String version) {

		String origin = getRequest().getHeader("Referer");

		URL url= null;
		try {
			url = new URL(origin);
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}

		String referUrl=null;

		if(url!=null)
		{
			referUrl=url.getProtocol()+"://"+url.getAuthority();
		}
		boolean bFlag=false;

		if(SysStringUtils.isNotEmpty(referUrl))
		{
			String corsMappingStr = SpringPropertiesUtil.getPropertiestValue("cors_mappings");
			if(SysStringUtils.isNotEmpty(corsMappingStr))
			{
				String[] corsMappings = corsMappingStr.split(",");

				for (String strUrl : corsMappings) {
					if(SysStringUtils.isEmpty(strUrl))
						continue;

					if(strUrl.equals(referUrl))
					{
						bFlag=true;
						break;
					}
				}
			}

		}

		if(bFlag)
		{
			String safeToken = safeTokenUtil.generateToken(version).getKey();
			return success(safeToken);
		}

		return error("权限不够");
	}

}
